package com.hkfn.rfb.common.utils;

import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.util.Log;
import android.widget.Toast;

import androidx.core.content.FileProvider;

import com.hkfn.rfb.common.bean.ConstData;
import com.xh.common.thread.AsyncExecutor;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;

/**
 * Created by zf-note on 2017/7/12.
 */
public class FileUtil {

    public static class DownloadImagesTask extends AsyncTask<String, Integer, Boolean> {

        private Context context;
        private String path;
        private String successTip;
        private String errorTip;

        public DownloadImagesTask(String path, Context context,
                                  String successTip, String errorTip) {
            super();
            this.path = path;
            this.context = context;
            this.successTip = successTip;
            this.errorTip = errorTip;
        }

        @Override
        protected Boolean doInBackground(String... params) {
            // TODO Auto-generated method stub
            boolean isSuccess = false;
            if (Utils.sdCardIsAvailable()) {
                int length = params.length;
                if (length > 0) {
                    try {
                        File dir = new File(path);
                        if (!dir.exists()) {
                            dir.mkdirs();
                        }
                        for (int i = 0; i < length; i++) {
                            Utils.downloadImageAndSave(params[i], path + "/" + System.currentTimeMillis() + params[i].substring(params[i].lastIndexOf(".")));
                        }
                        isSuccess = true;
                    } catch (Exception e) {
                        isSuccess = false;
                    }
                }
            } else {
                errorTip = "本地存储不可用，无法下载";
            }
            return isSuccess;
        }

        @Override
        protected void onPostExecute(Boolean result) {
            // TODO Auto-generated method stub
            super.onPostExecute(result);
            if (null != context) {
                if (result) {
                    Toast.makeText(context, successTip, Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(context, errorTip, Toast.LENGTH_SHORT).show();
                }
            }
        }
    }

    /**
     * 文件下载工具类
     */
    public static class DownloadFileTask extends AsyncTask<String, Integer, Boolean> {

        private String path;
        private DownloadOverAction downloadOverAction;

        public DownloadOverAction getDownloadOverAction() {
            return downloadOverAction;
        }

        public void setDownloadOverAction(DownloadOverAction downloadOverAction) {
            this.downloadOverAction = downloadOverAction;
        }

        public DownloadFileTask(String path) {
            super();
            this.path = path;
        }

        @Override
        protected Boolean doInBackground(String... params) {
            // TODO Auto-generated method stub
            boolean isSuccess = false;
            int length = params.length;
            if (length > 0) {
                try {
                    File dir = new File(path);
                    if (!dir.exists()) {
                        dir.mkdirs();
                    } else {
                        if (dir.list().length > 0) {
                            // 删除原有的
                            DataCleanManager.cleanCustomCache(path);
                            dir.mkdirs();
                        }
                    }
                    for (int i = 0; i < length; i++) {
                        if (StringUtils.isEmpty(params[i])) {
                            continue;
                        }
                        Utils.downloadImageAndSave(params[i], path + params[i].substring(params[i].lastIndexOf("/")));
                    }
                    isSuccess = true;
                } catch (Exception e) {
                    isSuccess = false;
                }
            }
            return isSuccess;
        }

        @Override
        protected void onPostExecute(Boolean result) {
            // TODO Auto-generated method stub
            super.onPostExecute(result);
            if (null != downloadOverAction) {
                downloadOverAction.overAction(result);
            }
        }

        public interface DownloadOverAction {
            void overAction(Boolean result);
        }
    }

    /**
     * 保存文件
     * @param filePath
     * @param fileName
     * @param content
     * @return
     */
    public static boolean saveFile(final String filePath, final String fileName, final String content) {
        // 有外存储
        if (Utils.sdCardIsAvailable()) {
            AsyncExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    FileOutputStream fos = null;
                    try {
                        File dir = new File(filePath);
                        if (!dir.exists()) {
                            dir.mkdirs();
                        }
                        fos = new FileOutputStream(filePath + fileName);
                        fos.write(content.getBytes());
                    } catch (Exception e) {
                        if (null != fos) {
                            try {
                                fos.close();
                            } catch (IOException e1) {
                                e1.printStackTrace();
                            }
                        }
                    } finally {
                        if (null != fos) {
                            try {
                                fos.close();
                            } catch (IOException e1) {
                                e1.printStackTrace();
                            }
                        }
                    }
                }
            });
            return true;
        }
        return false;
    }

    /**
     * 删除文件，可以是文件或文件夹
     *
     * @param fileName
     *            要删除的文件名
     * @return 删除成功返回true，否则返回false
     */
    public static boolean delete(String fileName) {
        File file = new File(fileName);
        if (!file.exists()) {
            return false;
        } else {
            if (file.isFile())
                return deleteFile(fileName);
            else
                return deleteDirectory(fileName);
        }
    }

    /**
     * 删除单个文件
     *
     * @param fileName
     *            要删除的文件的文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    public static boolean deleteFile(String fileName) {
        File file = new File(fileName);
        // 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
        if (file.exists() && file.isFile()) {
            return file.delete();
        } else {
            return false;
        }
    }

    /**
     * 删除目录及目录下的文件
     *
     * @param dir
     *            要删除的目录的文件路径
     * @return 目录删除成功返回true，否则返回false
     */
    public static boolean deleteDirectory(String dir) {
        // 如果dir不以文件分隔符结尾，自动添加文件分隔符
        if (!dir.endsWith(File.separator))
            dir = dir + File.separator;
        File dirFile = new File(dir);
        // 如果dir对应的文件不存在，或者不是一个目录，则退出
        if ((!dirFile.exists()) || (!dirFile.isDirectory())) {
            System.out.println("删除目录失败：" + dir + "不存在！");
            return false;
        }
        boolean flag = true;
        // 删除文件夹中的所有文件包括子目录
        File[] files = dirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            // 删除子文件
            if (files[i].isFile()) {
                flag = deleteFile(files[i].getAbsolutePath());
                if (!flag)
                    break;
            }
            // 删除子目录
            else if (files[i].isDirectory()) {
                flag = deleteDirectory(files[i]
                        .getAbsolutePath());
                if (!flag)
                    break;
            }
        }
        if (!flag) {
            return false;
        }
        // 删除当前目录
        if (dirFile.delete()) {
            return true;
        } else {
            return false;
        }
    }

    public static String getAbsolutePath(final Context context, final Uri uri) {
        // DocumentProvider
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }

                // TODO handle non-primary volumes
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {

                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{
                        split[1]
                };

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {
            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     *
     * @param context       The context.
     * @param uri           The Uri to query.
     * @param selection     (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     */
    public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {
                column
        };

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }


    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    /**
     * 安装app
     * @param filePath
     * @param context
     */
    public static boolean install(String filePath, Context context) {
        try {
            Intent intent = getInstallIntent(filePath, context);
            if (null != intent) {
                context.startActivity(intent);
                return true;
            }
        } catch (Exception e) {

        }
        return false;
    }


    // true :安装成功
    public static boolean install(String apkPath) {// apkPath:apk的存储路径
        boolean result = false;
        DataOutputStream dataOutputStream = null;
        BufferedReader errorStream = null;
        try {
            // 申请su权限
            Process process = Runtime.getRuntime().exec("su");
            dataOutputStream = new DataOutputStream(process.getOutputStream());
            // 执行pm install命令
            Log.e("xuhan", "要安装的apk路径:" + apkPath);
            String command = "pm install -t -r " + apkPath + "\n";// -t:允许apk被安装  -r :重新安装应用，且保留应用数据
            dataOutputStream.write(command.getBytes(Charset.forName("utf-8")));
            dataOutputStream.flush();
            dataOutputStream.writeBytes("exit\n");
            dataOutputStream.flush();
            process.waitFor();
            errorStream = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            String msg = "";
            String line;
            // 读取命令的执行结果
            while ((line = errorStream.readLine()) != null) {
                msg += line;
            }
            Log.e("xuhan", "install msg is " + msg);
            // 如果执行结果中包含Failure字样就认为是安装失败，否则就认为安装成功
            if (!msg.contains("Failure")) {
                result = true;
            }

        } catch (Exception e) {
            //ToastUtil.showLongToast(KursaalApp.context,"设备未Root,请先Root后再继续使用!");
            Log.e("xuhan",  e.getMessage());
            result = false;
        } finally {
            try {
                if (dataOutputStream != null) {
                    dataOutputStream.close();
                }
                if (errorStream != null) {
                    errorStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
                result = false;
                Log.e("xuhan", "install: " + e.toString());
            }
        }
        return result;
    }

    /**
     * 安装app
     * @param filePath
     * @param context
     */
    public static Intent getInstallIntent(String filePath, Context context) {
        try {
            File apkFile = new File(filePath);
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            Uri data;
            if (Build.VERSION.SDK_INT >= 24) {
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION);
                String authority = context.getPackageName() + ".fileprovider";
                data = FileProvider.getUriForFile(
                        context
                        , authority
                        , apkFile);

            } else {
                data = Uri.fromFile(apkFile);
            }
            intent.setDataAndType(data, "application/vnd.android.package-archive");
            return intent;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     *  读SD中的文件
     */
    public static String readFileSdcardFile(String fileName){
        String res="";
        FileInputStream fin = null;
        try{
            fin = new FileInputStream(ConstData.INFO_LOCATION + fileName);

            int length = fin.available();
            if (length > 0) {

                byte[] buffer = new byte[length];
                fin.read(buffer);

                res = HexUtil.hexUTF82String(HexUtil.formatHexString(buffer));
            }

        } catch(Exception e){
            e.printStackTrace();
        }finally {
            if (null != fin){
                try {
                    fin.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return res;
    }

    /**
     * 存数据到本地文件
     * @param fileName
     * @param content
     */
    public static void saveContentToFile(String fileName, String content){
        AsyncExecutor.execute(new Runnable() {
            @Override
            public void run() {
                byte[] bytes = HexUtil.hexStringToBytes(HexUtil.string2HexUTF8(content));
                if (null == bytes){
                    bytes = new byte[]{};
                }
                String strFileName = "";
                if (createFile(ConstData.INFO_LOCATION, fileName)) {
                    strFileName = ConstData.INFO_LOCATION + fileName;
                }
                if ("" != strFileName) {
                    FileOutputStream fileStream;
                    try {
                        fileStream = new FileOutputStream(strFileName, true);
                        fileStream.write(bytes, 0, bytes.length);
                        fileStream.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    /**
     * 创建本地文件
     */
    public static boolean createFile(String strPath, String strFile) {
        File path = new File(strPath);
        if (!path.exists()) {
            try {
                if (!path.mkdirs()) {
                    return false;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        File file = new File(strPath + strFile);
        if (file.exists()) {
            file.delete();
        }

        try {
            if (!file.createNewFile()) {
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return true;
    }

}
